﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="TestHelper.cs" company="Collaboris Ltd.">
//   Copyright (c) Collaboris Ltd. All rights Reserved.
// </copyright>
// <summary>
//   Defines the TestHelper type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Collaboris.Saf.Actions.Wss.Tests
{
    using System;
    using System.Collections.Generic;

    using Engine;
    using Engine.Report;

    using Microsoft.SharePoint;
    using Microsoft.SharePoint.Administration;

    using SharePoint.Wss.Columns;
    using SharePoint.Wss.Webs;

    using Sharepoint.WSS.ContentTypes;

    using SharePoint.Wss.Lists;

    using Support.Entities;

    public static class TestHelper
    {

        /// <summary>
        /// Does the macro scoped to a farm
        /// </summary>
        /// <param name="macroPath">The macro path.</param>
        /// <returns></returns>
        public static MacroReport DoMacro(string macroPath)
        {
            SafContext safContext = SafContext.CreateContext(SPFarm.Local, SPScope.Farm);
            //safContext.AddPlaceHolder("CurrentDirectory", TestGlobals.ProjectTestDirectory);
            safContext.ActionProperties.Add("CurrentDirectory", TestGlobals.ProjectTestDirectory);

            // lets get a reference to the Action and its action in the macro
            IMacro macro = MacroEngine.Create(macroPath, safContext);

            return macro.Do(safContext) as MacroReport;

            
        }

        /// <summary>
        /// Does the macro scoped to a farm
        /// </summary>
        /// <param name="macroPath">The macro path.</param>
        /// <returns></returns>
        public static MacroReport UndoMacro(string macroPath)
        {
            SafContext safContext = SafContext.CreateContext(SPFarm.Local, SPScope.Farm);
            //safContext.AddPlaceHolder("CurrentDirectory", TestGlobals.ProjectTestDirectory);
            safContext.ActionProperties.Add("CurrentDirectory", TestGlobals.ProjectTestDirectory);

            // lets get a reference to the Action and its action in the macro
            IMacro macro = MacroEngine.Create(macroPath, safContext);

            return macro.Undo(safContext) as MacroReport;
        }

        /// <summary>
        /// Does the macro.
        /// </summary>
        /// <param name="macroPath">The macro path.</param>
        /// <param name="siteUrl">The site URL.</param>
        /// <returns></returns>
        public static IMacro DoMacro(string macroPath, string siteUrl, out SafContext safContext)
        {
            return DoMacro(macroPath, siteUrl, string.Empty, out safContext);
        }

        /// <summary>
        /// Undoes the macro.
        /// </summary>
        /// <param name="macroPath">The macro path.</param>
        /// <param name="siteUrl">The site URL.</param>
        /// <returns></returns>
        public static IMacro UndoMacro(string macroPath, string siteUrl, SafContext context)
        {
            return UndoMacro(macroPath, siteUrl, string.Empty, context);
        }

        /// <summary>
        /// Does the macro.
        /// </summary>
        /// <param name="macroPath">The macro path.</param>
        /// <param name="siteUrl">The site URL.</param>
        /// <param name="testWebName">Name of the test web.</param>
        /// <returns></returns>
        public static IMacro DoMacro(string macroPath, string siteUrl, string testWebName, out SafContext safContext)
        {
            using (SPSite site = new SPSite(siteUrl))
            {
                SPWeb targetWeb;

                // lets go create a test web
                if (!string.IsNullOrEmpty(testWebName))
                {
                    using (SPWeb web = site.RootWeb)
                    {
                        CreateWeb(web, testWebName, ProcessMode.Do);
                        targetWeb = SPWebHelper.GetWeb(site, testWebName);    
                    }
                } 
                else
                {
                    targetWeb = site.RootWeb;
                }

                using (targetWeb)
                {
                    safContext = SafContext.CreateContext(targetWeb, SPScope.Web);
                    //safContext.AddActionProperty("CurrentDirectory", TestGlobals.ProjectTestDirectory, true);
                    safContext.ActionProperties.Add("CurrentDirectory", TestGlobals.ProjectTestDirectory, true);

                    // lets get a reference to the Action and its action in the macro
                    IMacro macro = MacroEngine.Create(macroPath, safContext);

                    macro.Do(safContext);

                    return macro;
                }
            }
        }

        /// <summary>
        /// Undoes the macro.
        /// </summary>
        /// <param name="macroPath">The macro path.</param>
        /// <param name="siteUrl">The site URL.</param>
        /// <param name="testWebName">Name of the test web.</param>
        /// <returns></returns>
        public static IMacro UndoMacro(string macroPath, string siteUrl, string testWebName, SafContext context)
        {
            using (SPSite site = new SPSite(siteUrl))
            {
                SPWeb targetWeb;
                
                if (!string.IsNullOrEmpty(testWebName))
                {
                    using (SPWeb web = site.RootWeb)
                    {
                        targetWeb = SPWebHelper.GetWeb(site, testWebName);
                    }
                }
                else
                {
                    targetWeb = site.RootWeb;
                }

                IMacro macro;
                using (targetWeb)
                {
                    SafContext safContext;
                    if (context == null)
                    {
                        safContext = SafContext.CreateContext(targetWeb, SPScope.Web);
                        safContext.ActionProperties.Add("CurrentDirectory", TestGlobals.ProjectTestDirectory, true);
                    }
                    else
                    {
                        safContext = context;
                    }

                    // lets get a reference to the Action and its action in the macro
                    macro = MacroEngine.Create(macroPath, safContext);
                    macro.Undo(safContext);
                }

                using (SPWeb web = site.RootWeb)
                {
                    CreateWeb(web, testWebName, ProcessMode.Undo);
                }

                return macro;
            }
        }

        private static void CreateWeb(SPWeb web, string testWebName, ProcessMode mode)
        {
            SafContext safContext = SafContext.CreateContext(web, SPScope.Web);

            // lets go create a test web
            if (!string.IsNullOrEmpty(testWebName))
            {
                safContext.ActionProperties.Add("TestWebName", testWebName, true);
                safContext.ActionProperties.Add("TestWebUrl", testWebName, true);

                string path = TestGlobals.ProjectTestDirectory + @"\Create_Test_Web.xml";
                IMacro createWebMacro = MacroEngine.Create(path, safContext);

                if (mode == ProcessMode.Do)
                    createWebMacro.Do(safContext);
                else
                    createWebMacro.Undo(safContext);
                
            }
        }
        
        /// <summary>
        /// creates a publishing site
        /// </summary>
        /// <param name="parentWebUrl">
        /// The site collection url.
        /// </param>
        /// <param name="title">
        /// The title.
        /// </param>
        /// <param name="webUrl">
        /// The web Url.
        /// </param>
        public static void CreatePublishingWeb(string parentWebUrl, string title, string webUrl)
        {
            using (SPSite site = new SPSite(parentWebUrl))
            {
                using (SPWeb parentWeb = site.OpenWeb())
                {
                    // Create a SOURCE test web
                    SPWebHelper.CreateWeb(parentWeb, true, title, "Unit Test Web", "BLANKINTERNET#0", webUrl, 1033, false, false);                                       
                }                
            }            
        }

        /// <summary>
        /// Creates the person list.
        /// </summary>
        /// <param name="web">The web.</param>
        /// <param name="delete">if set to <c>true</c> [delete].</param>
        /// <param name="fillWithData">if set to <c>true</c> [fill with data].</param>
        public static void CreatePersonList(SPWeb web, bool delete, bool fillWithData)
        {
            Person testEntity = new Person();
            testEntity.Gender = "Male";
            testEntity.Forename = "Mark";
            testEntity.Surname = "Jones";
            CreatePersonList(web, delete, fillWithData, new Person[] { testEntity });
        }

        public static SPList CreateTasksList(SPWeb web, bool delete, bool fillWithData)
        {
            Guid returnGuid = web.Lists.Add("TestTasks", "Whatever", SPListTemplateType.Tasks);

            SPList newList = web.Lists[returnGuid];

            if (fillWithData)
            {
                SPListItemCollection coll = newList.Items;
                SPListItem task = coll.Add();
                SPFieldUserValueCollection fv = new SPFieldUserValueCollection();

                // add the new user into the collection
                task["Title"] = "Created for testing";
                task["Description"] = "some desc";
                task.Update();
            }

            return newList;
        }

        /// <summary>
        /// Creates a test person list.
        /// </summary>
        /// <param name="web">The web.</param>
        /// <param name="delete">if set to <c>true</c> [delete].</param>
        /// <param name="fillWithData">if set to <c>true</c> [fill with data].</param>
        /// <param name="testEntities">The test entities.</param>
        public static void CreatePersonList(SPWeb web, bool delete, bool fillWithData, Person[] testEntities)
        {
            // now lets add our test list 
            web.AllowUnsafeUpdates = true;
            
            if (delete)
            {
                if (SPListHelper.ListExists(web, TestGlobals.Lists.PersonListName))
                {
                    web.Lists[TestGlobals.Lists.PersonListName].Delete();
                }
            }

            SPListHelper.CreateList(web, "Custom List", TestGlobals.Lists.PersonListName, "Person List", true);

            // Create the List fields
            AddFieldsToPersonList(web);

            // Go populate with a few rows of data
            if (fillWithData)
            {
                FillPersonListWithData(web, testEntities);
            }
        }

        /// <summary>
        /// Creates the type of the person content.
        /// </summary>
        /// <param name="web">The web.</param>
        /// <returns></returns>
        public static SPContentType GetNewPersonContentType(SPWeb web)
        {
            SPContentType personContentType = new SPContentType(
                    web.AvailableContentTypes["Item"], web.ContentTypes, "PersonContentType");

            // A string Field        
            web.Fields.Add("Title", SPFieldType.Text, false);        
        
            SPFieldLink fLink1 = new SPFieldLink(web.Fields["Title"]);        
            personContentType.FieldLinks.Add(fLink1);         
            
            // A required number field        
            web.Fields.Add("Forename", SPFieldType.Text, true);        
            SPFieldLink fLink2 = new SPFieldLink(web.Fields["Forename"]);        
            personContentType.FieldLinks.Add(fLink2);         
            
            // A Choice Field        
            web.Fields.Add("Gender", SPFieldType.Choice, false);        
            SPFieldChoice choicefield = (SPFieldChoice)web.Fields["Gender"];        
            
            // Add a group to the filed        
            choicefield.Group = "TestGroup";        
            
            // Add choices        
            choicefield.Choices.Add(string.Empty);        
            choicefield.Choices.Add("Male");        
            choicefield.Choices.Add("Female");        
            
            // Set the default choice        
            choicefield.DefaultValue = string.Empty;        
            choicefield.Update();        
            
            SPFieldLink fLink3 = new SPFieldLink(choicefield);        
            personContentType.FieldLinks.Add(fLink3);

            return personContentType;
        }

        /// <summary>
        /// Creates a test person list.
        /// </summary>
        /// <param name="web">The web.</param>
        /// <param name="delete">if set to <c>true</c> [delete].</param>
        /// <param name="fillWithData">if set to <c>true</c> [fill with data].</param>
        /// <param name="testEntities">The test entities.</param>
        public static void CreatePersonListWithContentType(SPWeb web, bool delete, bool fillWithData)
        {
            // now lets add our test list 
            web.AllowUnsafeUpdates = true;

            if (delete)
            {
                if (SPListHelper.ListExists(web, TestGlobals.Lists.PersonListName))
                {
                    web.Lists[TestGlobals.Lists.PersonListName].Delete();
                }
            }

            SPListHelper.CreateList(web, "Custom List", TestGlobals.Lists.PersonListName, "Person List", true);


            SPList newList = SPListHelper.GetList(web, TestGlobals.Lists.PersonListName);

            // Create the List fields
            // AddFieldsToPersonList(web);
            SPContentType newType = GetNewPersonContentType(web);

            newList.ContentTypesEnabled = true;
            newList.ContentTypes.Add(newType);
            newList.Update();

            // Go populate with a few rows of data
            if (fillWithData)
            {
                // FillPersonListWithData(web, testEntities);
            }

            web.Update();
        }

        /// <summary>
        /// Deletes the web.
        /// </summary>
        /// <param name="parentWebUrl">The parent web URL.</param>
        /// <param name="webUrl">The web URL.</param>
        public static void DeleteWeb(string parentWebUrl, string webUrl)
        {
            using (SPSite site = new SPSite(parentWebUrl))
            {
                using (SPWeb srcWeb = site.OpenWeb(webUrl))
                {                 
                    SPWebHelper.DeleteWeb(srcWeb, true);            
                }
            }
        }

        /// <summary>
        /// Creates a Team Site
        /// </summary>
        /// <param name="parentWebUrl">
        /// The parent web url.
        /// </param>
        /// <param name="title">
        /// The title.
        /// </param>
        /// <param name="webUrl">
        /// The web url.
        /// </param>
        public static void CreateTeamSite(string parentWebUrl, string title, string webUrl)
        {
            using (SPSite site = new SPSite(parentWebUrl))
            {
                using (SPWeb parentWeb = site.OpenWeb())
                {
                    // Create a SOURCE test web
                    SPWebHelper.CreateWeb(parentWeb, true, title, "Unit Test Web", "STS#1", webUrl, 1033, false, false);
                }
            }
        }

        public static void CreateMeetingSite(string parentWebUrl, string title, string webUrl)
        {
            using (SPSite site = new SPSite(parentWebUrl))
            {
                using (SPWeb parentWeb = site.OpenWeb())
                {
                    // Create a SOURCE test web
                    SPWebHelper.CreateWeb(parentWeb, true, title, "Unit Test Publishing Web", "MPS#0", webUrl, 1033, false, false);
                }
            }
        }

                /// <summary>
        /// Adds the fields to person list.
        /// </summary>
        /// <param name="newWeb">The new web.</param>
        private static void AddFieldsToPersonList(SPWeb newWeb)
        {

            SPList personList = SPListHelper.GetList(newWeb, TestGlobals.Lists.PersonListName);

            // Add the person Fields to the list
            SPListHelper.AddFieldToList(newWeb, personList, TestGlobals.Fields.Forename,
                                            SPFieldType.Text, false);

            SPListHelper.AddFieldToList(newWeb, personList, TestGlobals.Fields.Surname,
                                            SPFieldType.Text, false);

            SPListHelper.AddFieldToList(newWeb, personList, TestGlobals.Fields.Gender,
                                            SPFieldType.Choice, false);

            // Create a Quick Choice in the new Web
            SPFieldChoice regionField = (SPFieldChoice)personList.Fields[TestGlobals.Fields.Gender];
            regionField.Choices.Add("Male");
            regionField.Choices.Add("Female");
            regionField.DefaultValue = "Male";
            regionField.Update();
        }

        /// <summary>
        /// Fills the person list with data.
        /// </summary>
        /// <param name="newWeb">The new web.</param>
        /// <param name="testEntities">The test entities.</param>
        private static void FillPersonListWithData(SPWeb newWeb, Person[] testEntities)
        {
            SPList personList = newWeb.Lists[TestGlobals.Lists.PersonListName];
            if (personList == null)
            {
                throw new NullReferenceException("Cannot find the Person List. Check it got created!");
            }

            foreach (Person person in testEntities)
            {
                SPListItem newItem = null;

                newItem = newWeb.Lists[TestGlobals.Lists.PersonListName].Items.Add();
                newItem[TestGlobals.Fields.Title] = person.Title;
                newItem[TestGlobals.Fields.Surname] = person.Surname;
                newItem[TestGlobals.Fields.Forename] = person.Forename;

                newItem.Update();
            }
        }

        /// <summary>
        /// Creates the type of the person content.
        /// </summary>
        /// <param name="web">The web.</param>
        /// <returns></returns>
        public static void CreateNewOrderContentType(SPWeb web)
        {

            // Add the person Fields to the list
            SiteColumnHelper.CreateNewFieldInWeb(web, "OrderFulfillDate", SPFieldType.DateTime, false, true);
            SiteColumnHelper.CreateNewFieldInWeb(web, "OrderSupplier", SPFieldType.Text, false, true);

            List<SPField> fields = new List<SPField>() {SiteColumnHelper.GetField(web, "OrderFulfillDate"), 
                SiteColumnHelper.GetField(web, "OrderSupplier") };

            SPContentTypeHelper.CreateContentType(web, "Order", fields, "Item", "My Group", true);
            
            
        }
    }
}
